package com.mudrov.collections.realization;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

import com.mudrov.collections.interfaces.CollectionToQueue;

public class ArrayListForQueue<E> implements CollectionToQueue<E> {

	protected int capacity = 10;
	protected int size = 0;
	@SuppressWarnings("unchecked")
	protected E[] arrayOfElements = (E[]) (new Object[capacity]);

	@SuppressWarnings("unchecked")
	@Override
	public boolean add(E e) {
		if (size == capacity) {
			E[] newArray = (E[]) (new Object[capacity *= 2]);
			System.arraycopy(arrayOfElements, 0, newArray, 0, size);
			arrayOfElements = newArray;
		}
		arrayOfElements[size++] = e;
		return true;
	}

	@Override
	public boolean addAll(Collection<? extends E> c) {
		for (E element : c)
			add(element);
		return true;
	}

	@Override
	public void clear() {
		size = 0;
	}

	@Override
	public boolean contains(Object o) {
		for (int i = 0; i < size; ++i)
			if (arrayOfElements[i].equals(o))
				return true;
		return false;
	}

	@Override
	public boolean containsAll(Collection<?> c) {
		for (Object element : c)
			if (!this.contains(element))
				return false;
		return true;
	}

	@Override
	public boolean isEmpty() {
		return size == 0 ? true : false;
	}

	@Override
	public Iterator<E> iterator() {
		return new ArrayListIterator();
	}

	@Override
	public boolean remove(Object o) {
		int position = positionOfElement(o);
		if (position == -1)
			return false;
		System.arraycopy(arrayOfElements, 0, arrayOfElements, 0, position);
		System.arraycopy(arrayOfElements, position + 1, arrayOfElements,
				position, size - position - 1);
		--size;
		return true;
	}

	private int positionOfElement(Object o) {
		for (int i = 0; i < size; ++i)
			if (arrayOfElements[i].equals(o))
				return i;
		return -1;
	}

	@Override
	public boolean removeAll(Collection<?> c) {
		boolean hasDeleted = false;
		for (Object element : c)
			if (remove(element))
				hasDeleted = true;
		return hasDeleted;
	}

	@Override
	public boolean retainAll(Collection<?> c) {
		boolean hasDeleted = false;
		for (E element : this)
			if (!c.contains(element)) {
				remove(element);
				hasDeleted = true;
			}
		return hasDeleted;
	}

	@Override
	public int size() {
		return size;
	}

	@Override
	public Object[] toArray() {

		return Arrays.copyOf(arrayOfElements, size);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T[] toArray(T[] a) {
		if (a.length < size)
			return (T[]) Arrays.copyOf(arrayOfElements, size, a.getClass());
		System.arraycopy(arrayOfElements, 0, a, 0, size);
		if (a.length > size)
			a[size] = null;
		return a;
	}

	public class ArrayListIterator implements Iterator<E> {

		private int currentElement = 0;

		@Override
		public boolean hasNext() {
			return currentElement < size;
		}

		@Override
		public E next() {
			return arrayOfElements[currentElement++];
		}

		@Override
		public void remove() {
			removeByIndex(currentElement);
		}

	}

	private void removeByIndex(int position) {
		System.arraycopy(arrayOfElements, 0, arrayOfElements, 0, position);
		System.arraycopy(arrayOfElements, position + 1, arrayOfElements,
				position, size - position - 1);
		--size;
	}
	
}
